package com.lottery.im.module.tim.presenter;

import android.app.Activity;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.lottery.im.MyApplication;
import com.lottery.im.api.ApiClient;
import com.lottery.im.api.RetryWithDelay;
import com.lottery.im.api.observer.BaseListObserver;
import com.lottery.im.api.observer.ShowTipObserver;
import com.lottery.im.api.result.entity.SingleRedPacketsReceived;
import com.lottery.im.api.result.entity.UserOnlineState;
import com.lottery.im.constant.Constants;
import com.lottery.im.module.tim.event.GroupEvent;
import com.lottery.im.module.tim.event.MessageEvent;
import com.lottery.im.module.tim.event.RefreshEvent;
import com.lottery.im.module.tim.viewfeatures.ChatView;
import com.lottery.im.util.DateUtils;
import com.tencent.imsdk.TIMCallBack;
import com.tencent.imsdk.TIMConversation;
import com.tencent.imsdk.TIMConversationType;
import com.tencent.imsdk.TIMElemType;
import com.tencent.imsdk.TIMGroupMemberInfo;
import com.tencent.imsdk.TIMManager;
import com.tencent.imsdk.TIMMessage;
import com.tencent.imsdk.TIMValueCallBack;
import com.tencent.imsdk.ext.group.TIMGroupDetailInfo;
import com.tencent.imsdk.ext.group.TIMGroupManagerExt;
import com.tencent.imsdk.ext.group.TIMGroupSelfInfo;
import com.tencent.imsdk.ext.message.TIMConversationExt;
import com.tencent.imsdk.ext.message.TIMMessageDraft;
import com.tencent.imsdk.ext.message.TIMMessageLocator;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.TimeUnit;

/**
 * 聊天界面逻辑
 */
public class ChatPresenter implements Observer {

  private ChatView view;
  private TIMConversation conversation;
  private boolean isGetingMessage = false;
  private final int LAST_MESSAGE_NUM = 20;

  public ChatPresenter(ChatView view, String identify, TIMConversationType type) {
    this.view = view;
    conversation = TIMManager.getInstance().getConversation(type, identify);
  }

  /**
   * 加载页面逻辑
   */
  public void start() {
    //注册消息监听
    MessageEvent.getInstance().addObserver(this);
    //注册刷新监听
    RefreshEvent.getInstance().addObserver(this);
    //注册群关系监听
    GroupEvent.getInstance().addObserver(this);
    getMessage(null);
    TIMConversationExt timConversationExt = new TIMConversationExt(conversation);
    if (timConversationExt.hasDraft()) {
      if (null != view) {
        view.showDraft(timConversationExt.getDraft());
      }
    }
  }

  /**
   * 中止页面逻辑
   */
  public void stop() {
    //注销消息监听
    MessageEvent.getInstance().deleteObserver(this);
    RefreshEvent.getInstance().deleteObserver(this);
    GroupEvent.getInstance().deleteObserver(this);
    view = null;
  }

  /**
   * 获取聊天TIM会话
   */
  public TIMConversation getConversation() {
    return conversation;
  }

  /**
   * 发送消息
   *
   * @param message 发送的消息
   */
  public void sendMessage(final TIMMessage message) {
    conversation.sendMessage(message, new TIMValueCallBack<TIMMessage>() {
      @Override
      public void onError(int code, String desc) {//发送消息失败
        //错误码code和错误描述desc，可用于定位请求失败原因
        //错误码code含义请参见错误码表
        if (null != view) {
          view.onSendMessageFail(code, desc, message);
        }
      }

      @Override
      public void onSuccess(TIMMessage msg) {
        //发送消息成功,消息状态已在sdk中修改，此时只需更新界面
        MessageEvent.getInstance().onNewMessage(null);
      }
    });
    //message对象为发送中状态
    MessageEvent.getInstance().onNewMessage(message);
  }

  /**
   * 发送在线消息
   *
   * @param message 发送的消息
   */
  public void sendOnlineMessage(final TIMMessage message) {
    conversation.sendOnlineMessage(message, new TIMValueCallBack<TIMMessage>() {
      @Override
      public void onError(int i, String s) {
        if (null != view) {
          view.onSendMessageFail(i, s, message);
        }
      }

      @Override
      public void onSuccess(TIMMessage message) {

      }
    });
  }

  /**
   * 发送在线消息
   *
   * @param message 发送的消息
   */
  public void revokeMessage(final TIMMessage message) {
    TIMConversationExt timConversationExt = new TIMConversationExt(conversation);
    timConversationExt.revokeMessage(message, new TIMCallBack() {
      @Override
      public void onError(int i, String s) {
        if (null != view) {
          view.showToast("revoke error " + s);
        }
      }

      @Override
      public void onSuccess() {
        MessageEvent.getInstance().onNewMessage(null);
      }
    });
  }

  /**
   * This method is called if the specified {@code Observable} object's
   * {@code notifyObservers} method is called (because the {@code Observable}
   * object has been updated.
   *
   * @param observable the {@link Observable} object.
   * @param data the data passed to {@link Observable#notifyObservers(Object)}.
   */
  @Override
  public void update(Observable observable, Object data) {
    if (observable instanceof MessageEvent) {
      if (data instanceof TIMMessage || data == null) {
        TIMMessage msg = (TIMMessage) data;
        if (msg == null || msg.getConversation().getPeer().equals(conversation.getPeer())
            && msg.getConversation().getType() == conversation.getType()) {
          if (null != view) {
            view.showMessage(msg);
          }
          //当前聊天界面已读上报，用于多终端登录时未读消息数同步
          readMessages();
        }

        if (null != msg && msg.getElementCount() > 0 && null != msg.getElement(0)
            && msg.getElement(0).getType() == TIMElemType.GroupTips) {
          getNotification(msg.getConversation().getPeer());
          getGroupUserOnline(msg.getConversation().getPeer());
        }
      } else if (data instanceof TIMMessageLocator) {
        TIMMessageLocator msg = (TIMMessageLocator) data;
        if (null != view) {
          view.showRevokeMessage(msg);
        }
      }
    } else if (observable instanceof RefreshEvent) {
      if (null != view) {
        view.clearAllMessage();
      }
      getMessage(null);
    } else if (observable instanceof GroupEvent) {
      GroupEvent.NotifyCmd cmd = (GroupEvent.NotifyCmd) data;
      switch (cmd.type) {
        case DEL:
          if (null != view) {
            view.updateGroup((String) cmd.data);
          }
          break;
      }
    }
  }

  /**
   * 获取消息
   *
   * @param message 最后一条消息
   */
  public void getMessage(@Nullable TIMMessage message) {
    if (!isGetingMessage) {
      isGetingMessage = true;
      TIMConversationExt timConversationExt = new TIMConversationExt(conversation);
      // getLocalMessage 本地缓存消息 getMessage 线上消息
      timConversationExt.getLocalMessage(LAST_MESSAGE_NUM, message,
          new TIMValueCallBack<List<TIMMessage>>() {
            @Override
            public void onError(int i, String s) {
              isGetingMessage = false;
            }

            @Override
            public void onSuccess(List<TIMMessage> timMessages) {
              isGetingMessage = false;
              if (null != view) {
                view.showMessage(timMessages);
              }
            }
          });
    }
  }

  /**
   * 设置会话为已读
   */
  public void readMessages() {
    TIMConversationExt timConversationExt = new TIMConversationExt(conversation);
    timConversationExt.setReadMessage(null, null);
  }

  /**
   * 保存草稿
   *
   * @param message 消息数据
   */
  public void saveDraft(TIMMessage message) {
    TIMConversationExt timConversationExt = new TIMConversationExt(conversation);
    timConversationExt.setDraft(null);
    if (message != null && message.getElementCount() > 0) {
      TIMMessageDraft draft = new TIMMessageDraft();
      for (int i = 0; i < message.getElementCount(); ++i) {
        draft.addElem(message.getElement(i));
      }
      timConversationExt.setDraft(draft);
    }
  }

  /**
   * @param identify 群ID
   * 获取群公告 已经发布更新阅读时间
   */
  public void getNotification(String identify) {
    List<String> ids = new ArrayList<>();
    ids.add(identify);
    TIMGroupManagerExt.getInstance().getGroupDetailInfo(ids,
        new TIMValueCallBack<List<TIMGroupDetailInfo>>() {
          @Override public void onError(int i, String s) {
          }

          @Override public void onSuccess(List<TIMGroupDetailInfo> timGroupDetailInfos) {
            // 确保群ID是对的
            if (null != timGroupDetailInfos && timGroupDetailInfos.size() > 0) {
              TIMGroupDetailInfo timGroupDetailInfo = timGroupDetailInfos.get(0);

              String groupNotification = timGroupDetailInfo.getGroupNotification();
              if (TextUtils.isEmpty(groupNotification)) return;

              // 获取自己的群内资料
              TIMGroupManagerExt.getInstance().getSelfInfo(identify,
                  new TIMValueCallBack<TIMGroupSelfInfo>() {
                    @Override public void onError(int i, String s) {

                    }

                    @Override public void onSuccess(TIMGroupSelfInfo timGroupSelfInfo) {
                      Map<String, byte[]> selfCustomInfo = timGroupSelfInfo.getCustomInfo();
                      if (null == selfCustomInfo || null == selfCustomInfo.get(
                          Constants.NOTICE_TIME)) {
                        // 自定义字段为空，表示一次群公告都没读过
                        showGroupNotification(identify, timGroupSelfInfo.getUser(),
                            groupNotification);
                        return;
                      }
                      Map<String, byte[]> groupCustomInfo = timGroupDetailInfo.getCustom();
                      // 群公告发布/更新时间
                      byte[] updateTime = groupCustomInfo.get(Constants.NOTICE_UPDATE_TIME);
                      byte[] readTime = selfCustomInfo.get(Constants.NOTICE_TIME);
                      String updateTimeStr = "";
                      if (null != updateTime) {
                        updateTimeStr = new String(updateTime);
                      }
                      String readTimeStr = new String(readTime);
                      if (updateTimeStr.compareTo(readTimeStr) > 0) {
                        showGroupNotification(identify, timGroupSelfInfo.getUser(),
                            groupNotification);
                      }
                    }
                  });

              // 群公告内容

            }
          }
        });
  }

  private void showGroupNotification(String groupId, String identify, String groupNotification) {
    if (null != view) {
      view.showGroupNotification(groupNotification);
    }
    // 读取完毕，上报自己的读取时间
    TIMGroupManagerExt.ModifyMemberInfoParam param =
        new TIMGroupManagerExt.ModifyMemberInfoParam(groupId, identify);
    Map<String, byte[]> customInfo = new HashMap<>();
    try {
      customInfo.put(Constants.NOTICE_TIME,
          DateUtils.millis2String(System.currentTimeMillis(), DateUtils.DEFAULT_ALL_SDF_EMPTY)
              .getBytes("utf-8"));
      param.setCustomInfo(customInfo);
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

    TIMGroupManagerExt.getInstance().modifyMemberInfo(param, new TIMCallBack() {
      @Override
      public void onError(int code, String desc) {
      }

      @Override
      public void onSuccess() {
      }
    });
  }

  /**
   * 获取群在线人数
   * 先获取成员，再把ID拼接到服务器请求
   *
   * @param id 群ID
   */
  public void getGroupUserOnline(String id) {

    TIMGroupManagerExt.getInstance().getGroupMembers(id,
        new TIMValueCallBack<List<TIMGroupMemberInfo>>() {
          @Override public void onError(int i, String s) {

          }

          @Override public void onSuccess(List<TIMGroupMemberInfo> timGroupMemberInfos) {
            if (null == view) return;
            StringBuffer ids = new StringBuffer();
            for (TIMGroupMemberInfo memberInfo : timGroupMemberInfos) {
              if (TextUtils.isEmpty(ids.toString())) {
                ids.append(memberInfo.getUser());
              } else {
                ids.append("," + memberInfo.getUser());
              }
            }
            imGetGroupUserOnline(ids.toString());
          }
        });
  }

  private void imGetGroupUserOnline(String ids) {
    ApiClient.getApiRetrofitInstance()
        .imGetGroupUserOnline(ids)
        .throttleFirst(2, TimeUnit.SECONDS)
        .retryWhen(new RetryWithDelay(100, 50000))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new BaseListObserver<UserOnlineState>() {

          @Override public void onStart() {

          }

          @Override public void onSuccess(List<UserOnlineState> t) {
            if (null == view) return;
            int onlineNum = 0;
            for (UserOnlineState state : t) {
              if (state.getState().equals("Online")) onlineNum++;
            }
            if (null != view) {
              view.showOnlineNum(onlineNum, t.size());
            }
          }

          @Override public void onFail(String code, String msg) {

          }

          @Override public void onException(String msg) {

          }

          @Override public void onFinish() {

          }
        });
  }

  /**
   * 获取自己的群内资料 （其他资料GroupInfo已做缓存，主要目前是获取我的群名片）
   *
   * @param identify 群ID
   */
  public void getSelfInfo(String identify) {
    TIMGroupManagerExt.getInstance().getSelfInfo(identify,
        new TIMValueCallBack<TIMGroupSelfInfo>() {
          @Override public void onError(int i, String s) {
          }

          @Override public void onSuccess(TIMGroupSelfInfo timGroupSelfInfo) {
            if (null != view) {
              view.getSelfGroupProfile(timGroupSelfInfo);
            }
          }
        });
  }

  /**
   * 用户领取单个红包
   *
   * @param id 红包ID
   */
  public void receiveSingleRedPackets(Activity activity, String id, String note) {
    ApiClient.getApiRetrofitInstance()
        .receiveSingleRedPackets(MyApplication.getInstance().getUserInfo().getUserId(),
            MyApplication.getInstance().getToken(), id)
        .throttleFirst(2, TimeUnit.SECONDS)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new ShowTipObserver<SingleRedPacketsReceived>(activity) {
          @Override public void onSuccess(SingleRedPacketsReceived singleRedPacketsReceived) {
            if (null != view) view.receiveRedPacketsSuce(singleRedPacketsReceived,note);
          }
        });
  }

  /**
   * 用户领取群聊红包
   *
   * @param id 红包ID
   */
  public void receiveRedPackets(Activity activity, String id, String note) {
    ApiClient.getApiRetrofitInstance()
        .receiveRedPackets(MyApplication.getInstance().getUserInfo().getUserId(),
            MyApplication.getInstance().getToken(), id)
        .throttleFirst(2, TimeUnit.SECONDS)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new ShowTipObserver<SingleRedPacketsReceived>(activity) {
          @Override public void onSuccess(SingleRedPacketsReceived singleRedPacketsReceived) {
            if (null != view) view.receiveRedPacketsSuce(singleRedPacketsReceived,note);
          }
        });
  }
}
